from flask import Flask

from flask import Flask,jsonify

#导入蓝图
from apps.short_url_app.urls import user_bp
from apps.redirect_app.urls import redirect_bp

#导入配置字典
from base.settings import envs
#导入restful对象
from ext import api
#导入跨域对象
from ext import cors
#导入db对象
from ext import db
#导入cache
from ext import cache
import eventlet

#使用redis作为cache缓存
cache_config_redis = {
    'CACHE_TYPE':'redis',
    'CACHE_REDIS_HOST':'127.0.0.1',
    'CACHE_REDIS_PORT':6637,
    # 'CACHE_REDIS_PASSWORD':'密码', #如果redis配置了密码
    'CACHE_REDIS_DB':0, #指定使用的redis的db，默认0-15
}

#使用内存做cache缓存
cache_config_mem = {
    'CACHE_TYPE':'simple'#使用内存作为cache
}

#跨域请求
cors_config = {
    "origins": "*", #所有域都允许
    "expose_headers": ["Content-Type", "token","x-requested-with"], #跨域请求头允许的
    "methods": ["GET", "POST","PUT","PATCH","OPTIONS","DELETE"], #跨域允许的请求方式
    "supports_credentials": True, #允许在cookies跨域
}

def create_app():
    #创建一个flask实例，传递__name__ ,是把当前文路径作为flask实例的根路径
    #static和templates都是创建在该路径下的
    app = Flask(__name__,static_folder='../static',template_folder='../templates')
    #在这里设置好静态目录和templates的目录
    eventlet.monkey_patch()  # 开启补丁机制
    '基本配置'
    #导入配置从类中
    app.config.from_object(envs.get('default'))

    '拓展配置'
    #配置db对象 将db对象与app进行绑定，orm对象与app绑定
    db.init_app(app)
    #配置restful
    api.init_app(app)
    #配置跨域，supports_credentials=True 允许携带cookies等信息
    cors.init_app(app,**cors_config) #【2、使用三方扩展解决跨域】
    #配置缓存
    cache.init_app(app=app,config=cache_config_redis)


    '蓝图注册'
    #蓝图注册
    app.register_blueprint(user_bp)
    app.register_blueprint(redirect_bp)

    '中间件'
    # 首个请求来时触发
    @app.before_first_request
    def before_first_request():
        from apps.short_url_app.models import ShortUrlModel
        from base.redis_pool import pool_redis
        from sqlalchemy import func
        from base.public import URL_MAX_ID_URL
        # 每次项目启动时，就将短地址的最大存到redis数据库中
        max_id = db.session.query(func.max(ShortUrlModel.id)).scalar()
        if not max_id:
            max_id = 0
        pool_redis.set(URL_MAX_ID_URL, max_id)
        print('最大的id值', max_id)

    ## 异常处理
    @app.errorhandler(Exception)
    def handle_exception(e):
        # 将异常错误写到日志文件中
        # app.logger.exception(str(e))
        # print(e, type(e))
        # 对异常错误的响应，使用api的格式
        return jsonify(code=500, message=str(e)), 200
    return app
